#!/usr/bin/python
# -*- coding:utf-8 -*-
import math
import sys
import os
import json
import time
import requests
import board
import logging
from PIL import Image, ImageDraw, ImageFont
from adafruit_bme280 import basic as adafruit_bme280

# 路径配置
picdir = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'pic')
libdir = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'lib')
if os.path.exists(libdir):
    sys.path.append(libdir)
from waveshare_epd import epd7in5_V2

# 显示参数配置
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 480
DASHBOARD_HEIGHT = 300  # 仪表盘区域高度
FONT_PATH = os.path.join(picdir, 'Font.ttc')
DATA_FILE = "env_data.json"
DEEPSEEK_API_KEY = "sk-vhqnvfrzrfqrichlptnuyzrbasnqowkfalkpmtmildygqmwe"

class DashboardRenderer:
    def __init__(self, font_path):
        self.font_title = ImageFont.truetype(font_path, 24)
        self.font_data = ImageFont.truetype(font_path, 20)
        self.font_advice = ImageFont.truetype(font_path, 18)

    def draw_gauge(self, draw, center, radius, value, min_val, max_val, label):
        """绘制半圆形仪表盘"""
        # 绘制外圆
        draw.arc((center[0]-radius, center[1]-radius, 
                center[0]+radius, center[1]+radius),
                180, 360, fill=0, width=3)
        
        # 计算指针角度（0-180度对应min-max）
        angle = 180 * (value - min_val) / (max_val - min_val)
        rad = math.radians(180 - angle)
        
        # 绘制指针
        pointer_end = (
            center[0] + radius * 0.8 * math.cos(rad),
            center[1] - radius * 0.8 * math.sin(rad)
        )
        draw.line([center, pointer_end], fill=0, width=3)
        
        # 添加标签
        draw.text((center[0]+20, center[1]+60), label, font=self.font_data, fill=0)
        draw.text((center[0]-20, center[1]+60), f"{value:.1f}", font=self.font_data, fill=0)
        
        # 添加量程标记
        for angle in [180, 225, 270, 315, 360]:
            rad = math.radians(angle)
            start = (
                center[0] + (radius-10)*math.cos(rad),
                center[1] - (radius-10)*math.sin(rad)
            )
            end = (
                center[0] + radius*math.cos(rad),
                center[1] - radius*math.sin(rad)
            )
            draw.line([start, end], fill=0, width=2)

    def draw_data_panel(self, draw, y_start, data):
        """绘制底部数据面板"""
        # 背景框
        draw.rectangle((10, y_start, SCREEN_WIDTH-10, SCREEN_HEIGHT-10), outline=0, width=2)
        
        # 分栏显示
        col_width = (SCREEN_WIDTH-40) // 3
        texts = [
            (f"温度\n{data['temp']}℃", (30, y_start+20)),
            (f"湿度\n{data['humidity']}%", (30+col_width, y_start+20)),
            (f"气压\n{data['pressure']}hPa", (30+2*col_width, y_start+20))
        ]
        
        for text, pos in texts:
            draw.text(pos, text, font=self.font_data, fill=0, align="center")

    def draw_advice(self, draw, y_start, advice):  
        """绘制AI建议区域"""  
        y = y_start + 100  
        draw.text((20, y), "AI建议:", font=self.font_title, fill=0)  
    
    # 自动换行处理  
        max_width = SCREEN_WIDTH - 40  
        lines = []  
        current_line = []  
    
        for word in advice.split():  
           test_line = ' '.join(current_line + [word])  
           # Replace getsize with getbbox for modern Pillow versions  
           bbox = self.font_advice.getbbox(test_line)  
           text_width = bbox[2] - bbox[0]  # right - left = width  
        
           if text_width < max_width:  
               current_line.append(word)  
           else:  
               lines.append(' '.join(current_line))  
               current_line = [word]  
        lines.append(' '.join(current_line))  
    
    # 绘制建议文本  
        for i, line in enumerate(lines[:3]):  # 最多显示3行  
           draw.text((30, y+40+(i*30)), line, font=self.font_advice, fill=0) 

class FarmSystem:
    def __init__(self):
        self.epd = epd7in5_V2.EPD()
        self.epd.init()
        self.renderer = DashboardRenderer(os.path.join(picdir, 'Font.ttc'))
        self.sensor = adafruit_bme280.Adafruit_BME280_I2C(board.I2C())

    def get_ai_advice(self, data):
        """获取AI建议（示例代码）"""
        prompt = f"""当前温室环境数据:
        温度{data['temp']}度
        湿度{data['humidity']}%
        气压{data['pressure']}hPa
        给出建议，请在40个字内精简回答："""
        
        try:
            response = requests.post(
                "https://api.siliconflow.cn/v1/chat/completions",
                headers={"Authorization": f"Bearer {DEEPSEEK_API_KEY}"},
                json={
                "model": "Pro/deepseek-ai/DeepSeek-V3",
                "stream": False,
                "messages": [{
                    "role": "user",
                    "content": prompt + "\n\n"  
                }],
                "temperature": 0.7
            },
                timeout=30
            )
            return response.json()['choices'][0]['message']['content']
        except Exception as e:
            return f"Api调用错误{str(e)}"

    def update_display(self, data):
        """更新全屏显示"""
        image = Image.new('1', (SCREEN_WIDTH, SCREEN_HEIGHT), 255)
        draw = ImageDraw.Draw(image)
        
        # 绘制仪表盘
        self.renderer.draw_gauge(draw, (200, 150), 100, data['temp'], 0, 40, "度")
        self.renderer.draw_gauge(draw, (600, 150), 100, data['humidity'], 0, 100, "%")
        
        # 绘制数据面板
        self.renderer.draw_data_panel(draw, DASHBOARD_HEIGHT, data)
        
        # 绘制AI建议
        advice = self.get_ai_advice(data)
        self.renderer.draw_advice(draw, DASHBOARD_HEIGHT, advice)
        
        self.epd.display(self.epd.getbuffer(image))

    def run(self):
        """主循环"""
        try:
            while True:
                data = {
                    "temp": round(self.sensor.temperature, 1),
                    "humidity": round(self.sensor.humidity, 1),
                    "pressure": round(self.sensor.pressure/100, 1)
                }
                self.update_display(data)
                time.sleep(300)  # 5分钟更新一次
                
        except KeyboardInterrupt:
            self.epd.sleep()

if __name__ == "__main__":
    logging.basicConfig(level=logging.INFO)
    FarmSystem().run()
